package cn.lg.soar.system.general.controller;

import cn.lg.soar.common.model.HttpResult;
import cn.lg.soar.common.model.PageQuery;
import cn.lg.soar.common.model.PageResult;
import cn.lg.soar.common.util.AssertUtil;
import cn.lg.soar.common.util.data.DataUtil;
import cn.lg.soar.core.annotations.IdempotentByParam;
import cn.lg.soar.core.annotations.constraints.Id;
import cn.lg.soar.database.base.controller.BaseController;
import cn.lg.soar.database.base.model.UpdateDisabledVo;
import cn.lg.soar.database.query.QueryParams;
import cn.lg.soar.mvc.annotations.*;
import cn.lg.soar.system.api.constant.ModuleConst;
import cn.lg.soar.system.general.entity.Dict;
import cn.lg.soar.system.general.entity.DictItem;
import cn.lg.soar.system.general.model.AddItemDTO;
import cn.lg.soar.system.general.model.DictItemVo;
import cn.lg.soar.system.general.service.IDictItemService;
import cn.lg.soar.system.general.service.IDictService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
@Validated
@Api(tags = "字典数据")
@RestController
@RequestMapping(ModuleConst.MODULE_NAME + "/dict-item")
public class DictItemController extends BaseController<DictItem, IDictItemService> {

    @Override
    protected Serializable getId(DictItem entity) {
        return entity.getId();
    }

    @Autowired
    private IDictService dictService;

    private final static String SUBJECT = "字典数据";

    @ApiOperation("获取单个字典数据")
    @GetMapping("listByCode")
    public HttpResult<List<DictItemVo>> listByCode(String typeCode){
        return HttpResult.data(this.service.listByCode(typeCode));
    }

    @ApiOperation("获取多个字典数据")
    @GetMapping("map")
    public HttpResult<Map<String, List<DictItemVo>>> map(@ApiParam("需要获取的字段code，为空返回所有字典") String[] codes){
        Set<String> set;
        if (codes == null || codes.length == 0) {
            set = new HashSet<>(dictService.codeList());
        } else {
            set = DataUtil.arrayToSet(codes);
        }
        return HttpResult.data(this.service.mapByCode(set));
    }

    @ApiOperation("添加字典选项")
    @PostMapping("add-item")
    public HttpResult<Void> addItem(@RequestBody @Valid AddItemDTO dto){
        // 校验code
        Dict dict = dictService.getOne(
                Wrappers.<Dict>lambdaQuery()
                        .select(Dict::getId)
                        .eq(Dict::getCode, dto.getTypeCode())
        );
        AssertUtil.notNull(dict, "字典code不存在");
        // 校验选项
        List<DictItem> list = service.list(
                Wrappers.<DictItem>lambdaQuery()
                        .select(DictItem::getLabel, DictItem::getValue, DictItem::getSort)
                        .eq(DictItem::getDictId, dict.getId())
        );
        for (DictItem x : list) {
            AssertUtil.isFalse(x.getLabel().equals(dto.getLabel()), "已存在相同选项");
        }
        // 生成数据
        DictItem dictItem = new DictItem();
        // 自动生成值和排序
        Set<Integer> valueSet = list.stream().map(DictItem::getValue).collect(Collectors.toSet());
        OptionalInt max = list.stream().mapToInt(DictItem::getSort).max();
        dictItem.setSort(max.getAsInt());
        for (int i = 0, len = valueSet.size() + 1; i < len; i++) {
            if (valueSet.contains(i)) {
                continue;
            }
            dictItem.setValue(i);
            break;
        }
        dictItem.setDictId(dict.getId());
        dictItem.setLabel(dto.getLabel());
        dictItem.setRemark(dto.getRemark());
        AssertUtil.isTrue(service.save(dictItem), "添加失败");
        return HttpResult.success();
    }

    @IdempotentByParam("#p0")
    @CreateMapping
    public HttpResult<Serializable> create(@RequestBody @Validated DictItem dict) {
        return super.createResult(dict);
    }

    @UpdateMapping
    public HttpResult<Void> update(@RequestBody @Validated DictItem dict) {
        return super.updateResult(dict);
    }

    @RemoveMapping
    public HttpResult<Void> remove(@RequestBody List<Long> ids) {
        return super.removeResult(ids);
    }

    @UpdateDisabledMapping
    public HttpResult<Void> updateDisabled(@RequestBody @Validated UpdateDisabledVo data) {
        this.service.updateDisabled(data.getIds(), data.getDisabled());
        return HttpResult.success(data.getDisabled() ? "禁用成功" : "启用成功");
    }

    @DetailMapping
    public HttpResult<DictItem> detail(@Id Long id) {
        return super.detailResult(id);
    }

    @QueryMapping
    public HttpResult<PageResult<DictItem>> query(PageQuery pageQuery, QueryParams params){
        return super.queryResult(pageQuery, params);
    }

    @ExportMapping
    public void exports(QueryParams params, HttpServletResponse resp){
        super.exportExcel(DictItemController.SUBJECT, params, resp);
    }

    @ImportMapping
    public HttpResult<Void> imports(HttpServletRequest req){
        return super.importExcel(req);
    }

}
